package com.candy.candylogservice.config;

import com.candy.candycommon.utils.ApplicationContentUtils;
import com.candy.candylogservice.dto.LogLinkDTO;
import com.candy.candylogservice.queue.LogQueue;
import com.candy.candylogservice.service.LogLinkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author suYanLong
 * @date 2022年10月26日 14:25
 */
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "rpc", name = "log.enable", havingValue = "true", matchIfMissing = true)
public class LogQueueConfig {

    @Resource
    RpcLogProperties rpcLogProperties;

    @Bean
    public RpcLogProperties getRpcLogProperties(){
        return new RpcLogProperties();
    }

    @PostConstruct
    public void logLinkQueue() {
        ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) ApplicationContentUtils.getApplicationContext().getBean("asyncTaskExecutor");
        executor.execute(() -> {
            for (; ; ) {
                log.info("处理异常发送日志问题");
                try {
                    if (rpcLogProperties.getEnableBatch()) { // 等待批量消费
                        // TODO 可以改造成批量
                        if (LogQueue.logLinkQueue.size() < rpcLogProperties.getBatchMaxSize()) {
                            LogLinkDTO linkDTO = LogQueue.logLinkQueue.poll(rpcLogProperties.getBatchMaxAwaitDurationInSeconds(), TimeUnit.SECONDS);
                        } else {
                            LogQueue.logLinkQueue.take();
                        }
                    } else { // 立即消费
                        LogLinkDTO logLinkDTO = LogQueue.logLinkQueue.take();
                        executor.execute(() -> {
                            try {
                                log.info("长轮训继续消费队列，{}", logLinkDTO);
                                LogLinkService logLinkService = ApplicationContentUtils.getBean(LogLinkService.class);
                                logLinkService.save(logLinkDTO);
                            } catch (Exception e) {
                                logLinkDTO.setNum(logLinkDTO.getNum() + 1);
                                if (logLinkDTO.getNum() > 5) {
                                    log.error("长轮训消费异常：{}", logLinkDTO);
                                } else {
                                    LogQueue.logLinkQueue.add(logLinkDTO);
                                }
                            }
                        });
                    }
                } catch (Exception e) {
                    log.error("长轮训消费异常", e);
                    e.printStackTrace();
                }
            }
        });
    }

}
